/*
 *
 *  Copyright (C) 2010 Tal Eisenberg
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package gui;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import tal.drivechain.chain.AbortChainException;
import tal.drivechain.chain.NodeListener;
import tal.drivechain.gui.CircularDragSlider;
import tal.drivechain.gui.GUIModule;
import tal.drivechain.matchers.VarMatcher;
import tal.drivechain.plugin.Channel;
import tal.drivechain.variable.types.DataType;
import tal.drivechain.variable.SetProperty.Flag;
import tal.drivechain.variable.VarTableAction;
import tal.drivechain.variable.Variable;

/**
 *
 * @author eisental
 */
public class Knob extends GUIModule implements ActionListener {
    private CircularDragSlider dragKnob;
    private VarMatcher releaseTrigger, trigger;
    private Variable onRelease;
    private Boolean releaseOnChange;
    private Variable varValue = new Variable("value", DataType.FLOAT, null, true);
    private VarTableAction setVarValue;

    @Override
    public void setupProperties() throws IllegalArgumentException, AbortChainException {
        setVarValue = new VarTableAction("value", VarTableAction.Action.SET_ANY);

        component = dragKnob = new CircularDragSlider();
        dragKnob.addActionListener(this);

        super.setupProperties();
    }

    @Override
    protected void msgReceived(Variable in, long timestamp, Channel channel) {
        if (trigger.matches(in, channel, this)) {
            //set value of the knob
            dragKnob.setValue((Double)DataType.FLOAT.cast(in.getValue(this)));
        } else if (releaseTrigger.matches(in, channel, this)) {
            release();
        }
    }

    @Override
    public void setColor(Color value) {
        super.setColor(value);
        dragKnob.setColor(color);
    }

    public void setTrigger(VarMatcher trigger) {
        this.trigger = trigger;
    } public VarMatcher getTrigger() { return trigger; }

    public void setReleaseTrigger(VarMatcher trigger) {
        releaseTrigger = trigger;
    } public VarMatcher getReleaseTrigger() { return releaseTrigger; }

    public void setReleaseOnChange(Boolean b) {
        releaseOnChange = b;
    } public Boolean getReleaseOnChange() { return releaseOnChange; }

    public void setOnRelease(Variable var) {
        onRelease = var;
    } public Variable getOnRelease() { return onRelease; }

    public void setValue(Double val) {
        if (val==null) val = dragKnob.getMin();
        dragKnob.setValue(val);
    } public double getValue() { return (dragKnob!=null?dragKnob.getValue():0); }

    public void setMaxValue(Double max) {
        dragKnob.setMax(max);
    } public double getMaxValue() { return (dragKnob!=null?dragKnob.getMax():0); }

    public void setMinValue(Double min) {
        dragKnob.setMin(min);
    } public double getMinValue() { return (dragKnob!=null?dragKnob.getMin():0); }

    public void setDragScale(Double scale) {
        dragKnob.setScale(scale);
    } public double getDragScale() { return (dragKnob!=null?dragKnob.getScale():0); }

    private void release() {
        varValue.setValue(dragKnob.getValue(), true);
        setVarValue.set(varValue, localVars, this);
        sendToOutputs(onRelease, -1);
    }

    public void actionPerformed(ActionEvent e) {
        for (NodeListener l : nodeListeners)
            l.propertyChanged(this, "value", dragKnob.getValue());
        if (releaseOnChange)
            release();
    }


}
